#ifndef RS_STRING_H
#define RS_STRING_H
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
using namespace std;

typedef wstring rs_string;
typedef vector<rs_string> rs_string_v;
typedef rs_string_v::iterator rs_string_v_it;
typedef string utf8_string;


void wstring_to_ascii (const rs_string& s, string &t);
void ascii_to_wstring (const string& s, rs_string& t);
void utf8_to_wstring (const string& s, rs_string& t);
void wstring_to_utf8 (const rs_string&s, string& t);

inline string stringed (const rs_string& s)
{ // todo: cleanup occurrences of 'stringed'
    string t;
    wstring_to_ascii (s, t);
    return t;
}
inline rs_string rs_stringed (const string& s)
{
    rs_string t;
    ascii_to_wstring (s, t);
    return t;
}
inline rs_string rs_stringed (const int n, const int base=10)
{
    wostringstream woss;
    woss << setbase(base) << n << dec;
    return woss.str();
}

rs_string rs_stringed (const size_t n, const rs_string& tsep=L"");

inline rs_string rs_stringed (const double x)
{
    wostringstream woss;
    woss << x;
    return woss.str();
}
inline int string_to_int (const rs_string& str)
{
    wistringstream wiss(str);
    int n;
    wiss >> n;
    return n;
}

inline unsigned string_to_unsigned (const rs_string& str)
{
    wistringstream wiss(str);
    unsigned n;
    wiss >> n;
    return n;
}

void to_lower (rs_string &s);
void to_lower (wchar_t &wc);
void to_lower (string &s);
void to_lower (char &c);
inline rs_string lower_case (const rs_string& s)
{
    rs_string t(s);
    to_lower (t);
    return t;
}

void to_upper (rs_string& s);
void to_upper (wchar_t &wc);
inline rs_string upper_case (const rs_string& s)
{
    rs_string t(s);
    to_upper (t);
    return t;
}

bool is_nonascii (const wchar_t wc);
bool is_upper (const wchar_t wc);
bool is_lower (const wchar_t wc);
bool is_lower (const rs_string& str);
bool is_alpha (const wchar_t wc/*, wd_mode wdm*/); // po_mode ... wdm_po
bool is_alpha (const rs_string &wsrc);
bool is_ident_char (const wchar_t wc);

bool is_any_alpha (const rs_string &wsrc);
void trim_all_non_ident_chars (rs_string &s);
void trim_spaces (rs_string &s);

void string_to_vec_delim (const rs_string& str, rs_string_v& vec, wchar_t delim);
void string_to_vec_arg (const rs_string& str, rs_string_v& vec);
void string_to_vec (const rs_string& str, rs_string_v& vec, const rs_string& delim_opt);
void vec_to_string (const rs_string_v& vec, rs_string& str, const rs_string& delim_opt);
rs_string nth_substring (const rs_string& str, size_t index, const rs_string& delim_opt);
inline rs_string concat (const rs_string& s1, const rs_string& s2, wchar_t delim) {
    return (s1.length()>0 && s2.length()>0) ? (s1 + delim + s2) : (s1+s2);
}

void replace_all (string& str, char a_find, char a_replace);
void replace_all (rs_string& str, wchar_t a_find, wchar_t a_replace);
void replace_all (rs_string& str, const wchar_t *a_find, const wchar_t *a_replace);
void replace_all (string& str, const char *a_find, const char *a_replace);
void replace_file_substring (rs_string& str, const wchar_t *a_find, const wchar_t *a_replace);
inline rs_string replace_file_name (const rs_string& str, const wchar_t *a_find, const wchar_t *a_replace) {
    rs_string result (str);
    replace_file_substring (result, a_find, a_replace);
    return result;
}


struct flag_text {
    unsigned   ft_flag;
    wchar_t*   ft_text;
};

bool string_to_flags (
    const rs_string& str,
    unsigned& flags,
    const flag_text ft[],
    const rs_string& desc,
    bool allow_several=true);
rs_string flags_to_string (unsigned flags, const flag_text ft[], const rs_string& delim=L",");

bool parse_item (
    const rs_string& item_str,
    rs_string& item_name,
    unsigned& item_type,
    const flag_text ft[],
    const rs_string& ft_desc);


inline const rs_string& choose_str (const rs_string& a, const rs_string& b) {
    // returns the first argument if it is non-empty
    // otherwise return the second one
    if (a.size()>0)
        return a;
    return b;
}
void strip_regex_start_end (rs_string& pattern, bool& is_start, bool& is_end);
rs_string regex_add_start_end (rs_string pattern, bool is_start, bool is_end);

unsigned count_syllables (const rs_string& word, unsigned &s1, unsigned & s2);


#endif
